很多既有系統中存在著用資料行名稱來定義資料儲存內容的設計
非正規化的資料表設計
這時就可以使用 CROSS APPLY 以資料行名稱定義的設計
轉換成以資料列為主的設計
情境
食譜成本資料表
此情境中食譜的資料表有下列成本:份數、時間與電力
使用不同欄位來代表對應的單位與消耗量
原始資料如下
Id	Name			Type01	Unit01	Value01	Type02	Unit02	Value02	Type03	Unit03	Value03
1	芹菜蔬煎餅		份數	人		2.000	時間	分鐘	5.000	NULL	NULL	NULL
2	蛋包日式咖哩飯	份數	人		4.000	時間	分鐘	30.000	電力	度		2.500
3	龍蝦味噌湯		份數	人		8.000	時間	分鐘	15.000	電力	度		1.350
透過 CROSS APPLY 指令就可以將上述資料表內容進行行與列的轉置
--食譜資料表
SELECT a.[Id]
	,a.[Name]
	,b.[Type]
	,b.[Unit]
	,b.[Value]
FROM @RecipeCost a
	CROSS APPLY (
		VALUES ([Type01],[Unit01],[Value01])
			,([Type02],[Unit02],[Value02])
			,([Type03],[Unit03],[Value03])
	) b (
		[Type],[Unit],[Value]
	)
WHERE [Type] IS NOT NULL
轉置完成後的資料內容
-------------------------------------------
Id	Name			Type	Unit	Value
-------------------------------------------
1	芹菜蔬煎餅		份數	人		2.000
1	芹菜蔬煎餅		時間	分鐘	5.000
2	蛋包日式咖哩飯	份數	人		4.000
2	蛋包日式咖哩飯	時間	分鐘	30.000
2	蛋包日式咖哩飯	電力	度		2.500
3	龍蝦味噌湯		份數	人		8.000
3	龍蝦味噌湯		時間	分鐘	15.000
3	龍蝦味噌湯		電力	度		1.350
轉置後就可以將資料表進行調整
將 Type 與 Unit 抽離後建立關聯 ... 等
使用 UNPIVOT 也可以達成類似的效果
下列為完整的 Transact-SQL 片段
可複製到 SQL Server 上執行並確認效果
--食譜資料表
DECLARE @RecipeCost AS TABLE
(
	[Id]			SMALLINT,
	[Name]			NVARCHAR(50),
	[Type01]		NVARCHAR(10),
	[Unit01]		NVARCHAR(5),
	[Value01]		DECIMAL(13,3),	
	[Type02]		NVARCHAR(10),
	[Unit02]		NVARCHAR(5),
	[Value02]		DECIMAL(13,3),
	[Type03]		NVARCHAR(10),
	[Unit03]		NVARCHAR(5),
	[Value03]		DECIMAL(13,3),
	PRIMARY KEY ([Id])
)
--初始化資料內容
INSERT INTO @RecipeCost (
	[Id],[Name]
	,[Type01],[Unit01],[Value01]
	,[Type02],[Unit02],[Value02]
	,[Type03],[Unit03],[Value03]
) VALUES (
	1,N'芹菜蔬煎餅'
	,N'份數',N'人',2
	,N'時間',N'分鐘',5
	,NULL,NULL,NULL
),(
	2,N'蛋包日式咖哩飯'
	,N'份數',N'人',4
	,N'時間',N'分鐘',30
	,N'電力',N'度',2.5
),(
	3,N'龍蝦味噌湯'
	,N'份數',N'人',8
	,N'時間',N'分鐘',15
	,N'電力',N'度',1.35
)
SELECT a.[Id]
	,a.[Name]
	,b.[Type]
	,b.[Unit]
	,b.[Value]
FROM @RecipeCost a
	CROSS APPLY (
		VALUES ([Type01],[Unit01],[Value01])
			,([Type02],[Unit02],[Value02])
			,([Type03],[Unit03],[Value03])
	) b (
		[Type],[Unit],[Value]
	)
WHERE [Type] IS NOT NULL